package v1

import (
	"fmt"
	"io"
	"mime/multipart"
	"os"
	"path/filepath"
	"strings"
	"time"
	"wms/config"
	"wms/pkg/common"
	"wms/pkg/logger"
	"wms/pkg/utils"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"go.uber.org/zap"
)

// UploadController 文件上传控制器
type UploadController struct {
	uploadDir string
}

// NewUploadController 创建文件上传控制器
func NewUploadController() *UploadController {
	uploadDir := "./static/uploads"
	imageDir := filepath.Join(uploadDir, "images")

	// 确保目录存在
	if err := os.MkdirAll(imageDir, 0755); err != nil {
		logger.Error("创建上传目录失败", zap.Error(err), zap.String("dir", imageDir))
	}

	return &UploadController{
		uploadDir: uploadDir,
	}
}

// UploadImage godoc
// @Summary 上传图片
// @Description 上传图片文件
// @Tags 文件上传
// @Accept multipart/form-data
// @Produce json
// @Security Bearer
// @Param file formData file true "图片文件"
// @Success 200 {object} common.Response{data=map[string]string} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /upload/image [post]
func (c *UploadController) UploadImage(ctx *gin.Context) {
	logger.Info("开始处理图片上传请求")

	// 获取上传文件
	file, err := ctx.FormFile("file")
	if err != nil {
		logger.Error("获取上传文件失败", zap.Error(err))
		common.Error(ctx, fmt.Errorf("获取上传文件失败: %s", err.Error()))
		return
	}

	// 验证文件类型
	if !isImageFile(filepath.Ext(file.Filename)) {
		logger.Warn("上传的文件不是图片", zap.String("filename", file.Filename))
		common.Error(ctx, fmt.Errorf("只支持图片文件(jpg,jpeg,png,gif)"))
		return
	}

	// 生成新的文件名
	filename := generateFilename(filepath.Ext(file.Filename))
	savePath := filepath.Join(c.uploadDir, "images", filename)

	// 保存文件
	if err := saveUploadedFile(file, savePath); err != nil {
		logger.Error("保存文件失败", zap.Error(err), zap.String("filename", filename))
		common.Error(ctx, fmt.Errorf("保存文件失败: %s", err.Error()))
		return
	}

	// 返回文件URL
	url := "/static/uploads/images/" + filename
	logger.Info("图片上传成功", zap.String("url", url))
	common.Success(ctx, gin.H{"url": url})
}

// 检查文件是否为图片
func isImageFile(ext string) bool {
	ext = strings.ToLower(ext)
	allowedExts := []string{".jpg", ".jpeg", ".png", ".gif"}
	for _, allowedExt := range allowedExts {
		if ext == allowedExt {
			return true
		}
	}
	return false
}

// 生成新的文件名
func generateFilename(ext string) string {
	ext = strings.ToLower(ext)
	newName := fmt.Sprintf("%s_%s%s",
		time.Now().Format("20060102150405"),
		strings.ReplaceAll(uuid.New().String(), "-", "")[:8],
		ext)
	return newName
}

// 保存上传的文件
func saveUploadedFile(file *multipart.FileHeader, dst string) error {
	src, err := file.Open()
	if err != nil {
		return err
	}
	defer src.Close()

	// 创建目标文件
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

	// 复制文件内容
	_, err = io.Copy(out, src)
	return err
}

// UploadFile 上传文件
func UploadFile(c *gin.Context) {
	file, err := c.FormFile("file")
	if err != nil {
		common.Error(c, fmt.Errorf("获取上传文件失败"))
		return
	}

	// 检查文件大小
	if file.Size > config.GetConfig().Upload.MaxSize*1024*1024 {
		common.Error(c, fmt.Errorf("文件大小不能超过 %dMB", config.GetConfig().Upload.MaxSize))
		return
	}

	// 检查文件类型
	ext := strings.ToLower(filepath.Ext(file.Filename))
	allowed := false
	for _, allowedType := range config.GetConfig().Upload.AllowedTypes {
		if ext == allowedType {
			allowed = true
			break
		}
	}
	if !allowed {
		common.Error(c, fmt.Errorf("不支持的文件类型"))
		return
	}

	// 生成文件名
	fileName := fmt.Sprintf("%d%s", time.Now().Unix(), ext)
	savePath := filepath.Join(config.GetConfig().Upload.SavePath, fileName)

	// 保存文件
	if err := utils.SaveUploadedFile(file, savePath); err != nil {
		common.Error(c, fmt.Errorf("保存文件失败"))
		return
	}

	common.Success(c, gin.H{
		"fileName": fileName,
		"filePath": savePath,
	})
}
